﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using WCBG.ToolsForUnity.Tools;


public class ActionInfo
{
    public string actionName;
    public int actionTime;  // 为0就是循环动作
}
public class LediActionInfo
{
    public PlayerAnimationController.PlayerAnimationEnum animationType;
    public string audioPath;
    public int audioDelayTime;
    public ActionInfo[] actionInfoArray;
    public string action_end_name;
    public int action_end_time;
    public uint nextActionID;
}

public class PlayerAnimationController : Singleton<PlayerAnimationController>, IEasyTimer, IEasyAudio, IEasyEffect
{

    private bool _bTimerCallback = true;
    public bool bTimerCallback
    {
        get { return _bTimerCallback; }
    }
    

    public enum PlayerAnimationEnum
    {
        /// <summary>
        /// 左下角半身
        /// </summary>
        LeftBottomToHalf = 0,
        /// <summary>
        /// 击掌动画
        /// </summary>
        Clap = 1,
    }


    private const float LEDI_IN_TIME = 0.3f;
    private const float LEDI_OUT_TIME = 0.3f;
    private const float LEDI_DELAY_START_TIME = 0.5f;
    private const float LEDI_DELAY_OUT_TIME = 0.5f;

    private Ease LEDI_IN_EASE = Ease.InQuad;
    private Ease LEDI_OUT_EASE = Ease.InQuad;

    private string scenePath = StudyPath.player_animation_scene_path;
    private string lediPath = StudyPath.player_ledi_path;


    private Camera m_camera;
    private Transform m_scene;
    private Transform m_effectParent;

    private LediActor m_lediActor;
    private GameObject m_hintEffect;
    private GameAudioSource m_currentAudio;
    private LediActionInfo m_currentInfo;

    private int m_currentSeq;
    private bool isAudioPlaying;
    private bool isLockInput;

    //public float leftBottomWidth = 550;
    //public float leftBottomHeight = -300; // 40;

    private Vector3 m_leftButtomStart;
    private Vector3 m_leftButtomEnd;
    private Vector3 m_clapStart;    // 击掌出生点
    private Vector3 m_clapEnd;  // 击掌中心店

    private System.Action m_completeCallback;

    private Dictionary<int, bool> m_animationDict = new Dictionary<int, bool>();
    private int animationSeq;


    public override void Init()
    {
        base.Init();
        _bTimerCallback = true;
        animationSeq = 1;

        m_scene = Res.LoadObj(scenePath).transform;
        m_scene.position = new Vector3(0, -9999, 0);
        m_camera = m_scene.GetComponentInChildren<Camera>();
        m_lediActor = Res.LoadObj(lediPath).AddComponentEx<LediActor>();
        m_lediActor.gameObject.SetActive(false);
        m_hintEffect = Res.LoadObj(StudyPath.math_traineffect_hint);
        m_hintEffect.transform.SetParent(m_lediActor.transform.GetComponentInChildren<BoxCollider>().transform);
        m_hintEffect.ResetTransformForLocal();
        m_hintEffect.SetActive(false);
        m_hintEffect.SetLayer(EGameLayerMask.PlayerAnimation);

        //m_leftButtomStart = m_camera.ScreenToWorldPoint(new Vector3(leftBottomWidth, -Screen.height, 500));
        m_leftButtomStart = m_camera.ScreenToWorldPoint(new Vector3(-Screen.width, -Screen.height * 0.27f, 500));
        m_leftButtomEnd = m_camera.ScreenToWorldPoint(new Vector3(Screen.width * 0.35f, -Screen.height * 0.27f, 500));
        m_clapStart = m_scene.Find("clap_start").position;
        m_clapEnd = m_scene.Find("clap_end").position;
        m_effectParent = m_scene.Find("effect_parent");

        EventBus.Instance.AddEventHandler(EventID.ON_GAMESTATE_STUDYENGLISH_EXIT, OnStudyGameExit);
        EventBus.Instance.AddEventHandler(EventID.ON_GAMESTATE_STUDYMATH_EXIT, OnStudyGameExit);
        EventBus.Instance.AddEventHandler(EventID.ON_GAMESTATE_STUDYGEOMETRY_EXIT, OnStudyGameExit);
        EventBus.Instance.AddEventHandler(EventID.ON_MATH_GAME_FLOW_EXIT, OnStudyGameExit); 
        EventBus.Instance.AddEventHandler(EventID.ON_MOUSE_BUTTON_DOWN, OnMouseDown);
    }

    public override void UnInit()
    {
        base.UnInit();
        _bTimerCallback = false;

        EventBus.Instance.RemoveEventHandler(EventID.ON_GAMESTATE_STUDYENGLISH_EXIT, OnStudyGameExit);
        EventBus.Instance.RemoveEventHandler(EventID.ON_GAMESTATE_STUDYMATH_EXIT, OnStudyGameExit);
        EventBus.Instance.RemoveEventHandler(EventID.ON_GAMESTATE_STUDYGEOMETRY_EXIT, OnStudyGameExit);
        EventBus.Instance.RemoveEventHandler(EventID.ON_MATH_GAME_FLOW_EXIT, OnStudyGameExit);
        EventBus.Instance.RemoveEventHandler(EventID.ON_MOUSE_BUTTON_DOWN, OnMouseDown);
    }

    private void OnStudyGameExit()
    {
        m_animationDict.Clear();
        m_lediActor.transform.DOKill();
        //m_lediActor.gameObject.SetActive(false);
        if (m_lediActor != null) GameObject.Destroy(m_lediActor.gameObject);
        if (m_hintEffect != null) GameObject.Destroy(m_hintEffect);
        if (m_scene != null) GameObject.Destroy(m_scene.gameObject);

        if (m_currentAudio != null) m_currentAudio.Stop();

        PlayerAnimationController.DestroyInstance();
    }

    private void OnMouseDown()
    {
        switch (m_currentInfo.animationType)
        {
            case PlayerAnimationEnum.Clap:

                if (isLockInput)
                    return;

                Transform target = FTools.GetRaycastHitTarget(m_camera, Input.mousePosition, 99999, (int)EGameLayerMask.PlayerAnimation);
                if (target != null && target.name == "right_hand")
                {
                    // 中止连续动画
                    if (m_animationDict.ContainsKey(m_currentSeq))
                        m_animationDict[m_currentSeq] = true;

                    if (m_hintEffect != null)
                        m_hintEffect.SetActive(false);
                    this.PlayEffectEx(StudyPath.effect_502003005, m_effectParent, 2.5f, EGameLayerMask.PlayerAnimation);
                    // 播放通用击掌音效
                    this.PlayAudioEx(StudyAudioName.t_1001);
                    if (!string.IsNullOrEmpty(m_currentInfo.action_end_name))
                    {
                        m_lediActor.CrossFade(m_currentInfo.action_end_name, 0.1f);
                    }

                    this.AddTimerEx(m_currentInfo.action_end_time, () =>
                    {
                        if (m_currentInfo.nextActionID > 0)
                        {
                            PlayNextAnimation(m_currentInfo.nextActionID, m_completeCallback);
                        }
                        else
                        {
                            this.AddTimerEx((int)(LEDI_DELAY_OUT_TIME * 1000), () =>
                            {
                                m_lediActor.transform.DOMove(m_clapStart, LEDI_OUT_TIME).SetEase(Ease.InQuad).OnComplete(() =>
                                {
                                    if (m_completeCallback != null)
                                        m_completeCallback();
                                    m_completeCallback = null;
                                });
                            });
                        }
                    });

                }
                break;
        }
    }







    // 表格数据控制播放
    public void PlayAnimaton(LediActionInfo info, System.Action callback = null)
    {
        PlayAnimaton(info, true, callback);
    }

    public void PlayAnimaton(LediActionInfo info, bool isStartPlay, System.Action callback = null)
    {
        m_currentInfo = info;
        m_completeCallback = callback;

        m_lediActor.gameObject.SetActive(true);
        switch (info.animationType)
        {
            case PlayerAnimationEnum.LeftBottomToHalf:

                PlayLediAnimation(m_leftButtomStart, m_leftButtomEnd, isStartPlay, info, callback);
                break;
            case PlayerAnimationEnum.Clap:

                PlayLediAnimation(m_clapStart, m_clapEnd, isStartPlay, info, callback);

                isLockInput = true;
                this.AddTimerEx(1000, () =>
                {
                    isLockInput = false;
                    if (m_hintEffect != null)
                        m_hintEffect.SetActive(true);
                });
                break;
        }
    }

    private void PlayNextAnimation(uint actionID, System.Action callback = null)
    {
        LediActionInfo info = this.GetLediActionInfoEx(actionID);
        if (info == null)
        {
            if (callback != null)
                callback();
            return;
        }
        m_currentInfo = info;
        m_completeCallback = callback;

        m_lediActor.gameObject.SetActive(true);
        PlayLediAnimation(m_clapStart, m_clapEnd, false, info, callback);
    }

    // 播放表里填的动画流程跟音效
    private void PlayLediAnimation(Vector3 startPoint, Vector3 endPoint, bool isStartPlay, LediActionInfo info, System.Action callback = null)
    {
        if (isStartPlay)
        {
            m_lediActor.transform.position = startPoint;
            m_lediActor.transform.DOMove(endPoint, LEDI_IN_TIME).SetEase(Ease.InQuad);
        }
        float waitTime = isStartPlay ? LEDI_IN_TIME + LEDI_DELAY_START_TIME : 0;

        this.AddTimerEx(waitTime, () => {

            PlayLediAnimation(info, () =>
            {
                switch (info.animationType)
                {
                    case PlayerAnimationEnum.LeftBottomToHalf:

                        this.AddTimerEx(LEDI_DELAY_OUT_TIME, () =>
                        {
                            m_lediActor.transform.DOMove(startPoint, LEDI_OUT_TIME).SetEase(Ease.InQuad).OnComplete(() =>
                            {
                                if (callback != null)
                                    callback();
                            });
                        });
                        break;
                }
            });
        });
    }

    private void PlayLediAnimation(LediActionInfo info, System.Action callback = null)
    {
        m_currentSeq = animationSeq++;
        m_animationDict.Add(m_currentSeq, false);

        PlayLediAnimation(m_currentSeq, info.actionInfoArray, 0);
        this.AddTimerEx(info.audioDelayTime, () =>
        {
            isAudioPlaying = true;
            PlayAudio(info.audioPath, () =>
            {
                isAudioPlaying = false;
                switch (info.animationType)
                {
                    case PlayerAnimationEnum.LeftBottomToHalf:

                        if (m_animationDict.ContainsKey(m_currentSeq))
                            m_animationDict[m_currentSeq] = true;
                        if (!string.IsNullOrEmpty(info.action_end_name))
                        {
                            m_lediActor.CrossFade(info.action_end_name, 0.1f);
                        }

                        this.AddTimerEx(info.action_end_time, () =>
                        {
                            if (callback != null)
                                callback();
                        });
                        break;
                }
            });
        });
    }

    private void PlayLediAnimation(int seq, ActionInfo[] infoArray, int animIndex)
    {
        if (!m_animationDict.ContainsKey(seq))
            return;
        if (animIndex >= infoArray.Length)
        {
            m_animationDict.Remove(seq);
            return;
        }

        bool isStop = m_animationDict[seq];
        if (isStop)
        {
            m_animationDict.Remove(seq);
            return;
        }

        ActionInfo actionInfo = infoArray[animIndex];
        m_lediActor.CrossFade(actionInfo.actionName, 0.1f);
        Debug.Log("Play ActionName:" + actionInfo.actionName + " ActonTime:" + actionInfo.actionTime);
        this.AddTimerEx(actionInfo.actionTime, () => {
            animIndex++;
            PlayLediAnimation(seq, infoArray, animIndex);
        });
    }




    private void PlayAudio(string path, System.Action callback = null)
    {
        m_currentAudio = AudioManager.Instance.PlaySound(path);
        this.AddTimerEx(m_currentAudio.Length, () =>
        {
            m_currentAudio = null;
            if (callback != null)
                callback();
        });
    }

    private void PlayAudio(uint audioID, System.Action callback = null)
    {
        m_currentAudio = this.PlayAudioEx(audioID);
        this.AddTimerEx(m_currentAudio.Length, () =>
        {
            m_currentAudio = null;
            if (callback != null)
                callback();
        });
    }




}
